aboutsummaryrefslogtreecommitdiff
path: root/src/routes/player/[player]/[profile]/+page.svelte
diff options
context:
space:
mode:
Diffstat (limited to 'src/routes/player/[player]/[profile]/+page.svelte')
-rw-r--r--src/routes/player/[player]/[profile]/+page.svelte383
1 files changed, 383 insertions, 0 deletions
diff --git a/src/routes/player/[player]/[profile]/+page.svelte b/src/routes/player/[player]/[profile]/+page.svelte
new file mode 100644
index 0000000..247619d
--- /dev/null
+++ b/src/routes/player/[player]/[profile]/+page.svelte
@@ -0,0 +1,383 @@
+<script lang="ts">
+ import { inventoryIconMap, skyblockItemToUrl } from '$lib/minecraft/inventory'
+ import FarmingContests from '$lib/sections/FarmingContests.svelte'
+ import Leaderboards from '$lib/sections/Leaderboards.svelte'
+ import Achievements from '$lib/sections/Achievements.svelte'
+ import Inventories from '$lib/sections/Inventories.svelte'
+ import Collections from '$lib/sections/Collections.svelte'
+ import { chooseDefaultBackground } from '$lib/backgrounds'
+ import BackgroundImage from '$lib/BackgroundImage.svelte'
+ import type { CleanMemberProfile } from '$lib/APITypes'
+ import Username from '$lib/minecraft/Username.svelte'
+ import StatList from '$lib/sections/StatList.svelte'
+ import Auctions from '$lib/sections/Auctions.svelte'
+ import Infobox from '$lib/sections/Infobox.svelte'
+ import Minions from '$lib/sections/Minions.svelte'
+ import Essence from '$lib/sections/Essence.svelte'
+ import Slayers from '$lib/sections/Slayers.svelte'
+ import type { MatcherFile } from 'skyblock-assets'
+ import Claimed from '$lib/sections/Claimed.svelte'
+ import Collapsible from '$lib/Collapsible.svelte'
+ import Skills from '$lib/sections/Skills.svelte'
+ import { generateInfobox } from '$lib/profile'
+ import Zones from '$lib/sections/Zones.svelte'
+ import Armor from '$lib/sections/Armor.svelte'
+ import Harp from '$lib/sections/Harp.svelte'
+ import Pets from '$lib/sections/Pets.svelte'
+ import Coop from '$lib/sections/Coop.svelte'
+ import Bank from '$lib/sections/Bank.svelte'
+ import type { PageData } from './$types'
+ import Header from '$lib/Header.svelte'
+ import Emoji from '$lib/Emoji.svelte'
+ import { cleanId } from '$lib/utils'
+ import Head from '$lib/Head.svelte'
+ import Toc from '$lib/Toc.svelte'
+
+ export let data: PageData & CleanMemberProfile
+
+ export let pack: MatcherFile = data.pack
+
+ let categories: string[] = []
+ function setCategories() {
+ categories = []
+ if (data.member.stats?.find(s => s.category === 'deaths')) categories.push('deaths')
+ if (data.member.stats?.find(s => s.category === 'kills')) categories.push('kills')
+ if (data.member.stats?.find(s => s.category === 'auctions')) categories.push('auctions')
+ if (data.member.stats?.find(s => s.category === 'fishing')) categories.push('fishing')
+ if (data.member.stats?.find(s => s.category === 'races')) categories.push('races')
+ if (data.member.stats?.find(s => s.category === 'misc')) categories.push('misc')
+ if (data.member.minions.some(m => m.levels.some(l => l))) categories.push('minions')
+ if (data.member.slayers && data.member.slayers.xp > 0) categories.push('slayers')
+ categories.push('zones')
+ if (data.member.collections && data.member.collections.length > 0)
+ categories.push('collections')
+ if (data.profile.bank.balance !== undefined) categories.push('bank')
+ if (data.member.harp.selected !== null) categories.push('harp')
+ if (data.member.essence.types.length > 0) categories.push('essence')
+ if (data.member.claimed && data.member.claimed.length > 0) categories.push('claimed')
+ if (data.member.pets.list.length > 0) categories.push('pets')
+ if (data.member.farmingContests.list.length > 0) categories.push('farming_contests')
+ if (data.member.coopInvitation) categories.push('co-op')
+ if (data.member.achievements) categories.push('achievements')
+ categories.push('leaderboards')
+ }
+
+ $: [data, setCategories()]
+ $: backgroundUrl = data.customization?.backgroundUrl ?? chooseDefaultBackground(data.member.uuid)
+ $: showingInventories =
+ data.member.inventories?.inventory || data.member.inventories?.personal_vault
+
+ $: profileName = data.member.left ? 'Removed' : data.member.profileName
+</script>
+
+{#if backgroundUrl}
+ <BackgroundImage url={backgroundUrl} />
+{/if}
+
+<Head
+ title="{data.member.username}'s SkyBlock profile ({profileName})"
+ description={generateInfobox(data).join('\n')}
+ metaTitle={(data.member.rank.name ? `[${data.member.rank.name}] ` : '') +
+ `${data.member.username}\'s SkyBlock profile (${profileName})`}
+/>
+<Header
+ backArrowHref="/player/{data.member.username}"
+ blurred={data.customization?.blurBackground ?? false}
+/>
+
+<main class:has-blurred-background={data.customization?.blurBackground && backgroundUrl}>
+ {#if data.customization?.blurBackground && backgroundUrl}
+ <div class="blurred-background-container-container">
+ <div class="blurred-background-container">
+ <img class="blurred-background" src={backgroundUrl} alt="Background" />
+ </div>
+ </div>
+ {/if}
+
+ <h1>
+ <!-- this is weird like this so svelte doesn't add whitespace -->
+ <Username player={data.member} headType="3d" />{#if data.customization?.emoji}<span
+ class="profile-emoji"><Emoji value={data.customization.emoji} /></span
+ >
+ {/if}
+ ({profileName})
+ </h1>
+
+ <!-- technoblade -->
+ {#if data.member.uuid == 'b876ec32e396476ba1158438d83c67d4'}
+ <div class="technoblade-never-dies">
+ <a href="https://www.curesarcoma.org">Technoblade never dies. <Emoji value="🕊️" /></a>
+ </div>
+ {/if}
+
+ <Infobox {data} />
+
+ <Toc {categories} />
+
+ {#if data.member.skills && data.member.skills.list.length > 0}
+ <section id="skills" class="profile-skills">
+ <div class="skill-heading-container">
+ <h2 class="inline-heading">Skills</h2>
+ <span class="average-skill">
+ {data.member.skills.average} avg.
+ </span>
+ </div>
+ <Skills {data} />
+ </section>
+ {/if}
+
+ <br />
+
+ <div>
+ <div id="categories">
+ {#if data.member.inventories?.armor}
+ <section id="armor" class:armor-float={showingInventories}>
+ <h2>Armor</h2>
+ <Armor {data} {pack} />
+ </section>
+ {/if}
+ {#if showingInventories}
+ <section id="inventories">
+ <h2>
+ {#if data.member.inventories?.inventory}
+ Inventories
+ {:else}
+ <img
+ class="inventory-tab-icon"
+ loading="lazy"
+ src={skyblockItemToUrl(inventoryIconMap.personal_vault, pack)}
+ alt={cleanId('personal_vault')}
+ />
+ Personal Vault
+ {/if}
+ </h2>
+ <Inventories {data} {pack} />
+ </section>
+ {/if}
+ {#if data.member.stats}
+ {#each categories as category}
+ {#if data.member.stats?.find(s => s.category === category)}
+ <section>
+ <Collapsible id={category}>
+ <h2 slot="title">{cleanId(category)}</h2>
+ {#if category == 'auctions'}
+ <Auctions
+ stats={data.member.stats.filter(s => s.category === category)}
+ {data}
+ {pack}
+ />
+ {:else}
+ <StatList stats={data.member.stats.filter(s => s.category === category)} />
+ {/if}
+ </Collapsible>
+ </section>
+ {/if}
+ {/each}
+ {/if}
+ {#if categories.includes('minions')}
+ <section>
+ <Collapsible id="minions">
+ <h2 slot="title">Minions</h2>
+ <Minions {data} />
+ </Collapsible>
+ </section>
+ {/if}
+ {#if categories.includes('slayers')}
+ <section>
+ <Collapsible id="slayers">
+ <h2 slot="title">Slayers</h2>
+ <Slayers {data} />
+ </Collapsible>
+ </section>
+ {/if}
+ <section>
+ <Collapsible id="zones">
+ <h2 slot="title">Zones</h2>
+ <Zones {data} />
+ </Collapsible>
+ </section>
+ {#if categories.includes('collections')}
+ <section>
+ <Collapsible id="collections">
+ <h2 slot="title">Collections</h2>
+ <Collections {data} {pack} />
+ </Collapsible>
+ </section>
+ {/if}
+ {#if categories.includes('bank')}
+ <section>
+ <Collapsible id="bank">
+ <h2 slot="title">Bank</h2>
+ <Bank {data} />
+ </Collapsible>
+ </section>
+ {/if}
+ {#if categories.includes('harp')}
+ <section>
+ <Collapsible id="harp">
+ <h2 slot="title">Harp</h2>
+ <Harp {data} />
+ </Collapsible>
+ </section>
+ {/if}
+ {#if categories.includes('essence')}
+ <section>
+ <Collapsible id="essence">
+ <h2 slot="title">Essence</h2>
+ <Essence {data} />
+ </Collapsible>
+ </section>
+ {/if}
+ {#if categories.includes('claimed')}
+ <section>
+ <Collapsible id="claimed">
+ <h2 slot="title">Claimed</h2>
+ <Claimed {data} />
+ </Collapsible>
+ </section>
+ {/if}
+ {#if categories.includes('pets')}
+ <section>
+ <Collapsible id="pets">
+ <h2 slot="title">Pets</h2>
+ <Pets {data} />
+ </Collapsible>
+ </section>
+ {/if}
+ {#if categories.includes('farming_contests')}
+ <section>
+ <Collapsible id="farming-contests">
+ <h2 slot="title">Farming Contests</h2>
+ <FarmingContests {data} />
+ </Collapsible>
+ </section>
+ {/if}
+ {#if categories.includes('co-op')}
+ <section>
+ <Collapsible id="co-op">
+ <h2 slot="title">Co-op</h2>
+ <Coop {data} />
+ </Collapsible>
+ </section>
+ {/if}
+ {#if categories.includes('achievements')}
+ <section>
+ <Collapsible id="achievements">
+ <h2 slot="title">Achievements</h2>
+ <Achievements {data} />
+ </Collapsible>
+ </section>
+ {/if}
+ <section>
+ <Collapsible id="leaderboards">
+ <h2 slot="title">Leaderboards</h2>
+ <Leaderboards {data} />
+ </Collapsible>
+ </section>
+ </div>
+ </div>
+</main>
+
+<style>
+ main {
+ position: relative;
+ }
+ .profile-emoji {
+ display: inline;
+ }
+ .profile-skills {
+ display: inline-block;
+ position: absolute;
+ margin: 0.75em 1em 1em 1em;
+ }
+
+ #armor.armor-float {
+ float: left;
+ }
+
+ #armor {
+ margin-right: 2em;
+ height: 16em;
+ }
+
+ #inventories {
+ display: inline-block;
+ min-height: 16em;
+ }
+
+ section {
+ max-width: fit-content;
+ }
+
+ .blurred-background-container-container {
+ position: absolute;
+ width: 47rem;
+ height: calc(100% + 1em);
+ z-index: -9;
+ overflow: hidden;
+ clip: rect(-1em, auto, auto, -2em);
+ }
+ .blurred-background {
+ position: fixed;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ z-index: -10;
+ object-fit: cover;
+ background-blend-mode: overlay;
+ filter: blur(1em) brightness(0.6);
+ }
+ @media only screen and (max-width: 1400px) {
+ .blurred-background-container-container {
+ left: calc(5em + 5%);
+ width: 90%;
+ clip: rect(-1.7em, auto, auto, -10em);
+ }
+ main {
+ margin-top: 0.75em;
+ }
+ }
+ @media only screen and (max-width: 1040px) {
+ .profile-skills {
+ position: unset;
+ display: block;
+ width: max-content;
+ }
+ .blurred-background-container-container {
+ left: 0 !important;
+ width: 100vw !important;
+ }
+ }
+
+ .skill-heading-container {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: fit-content;
+ }
+ .skill-heading-container h2 {
+ display: inline-block;
+ margin-right: 0.4em;
+ margin-bottom: 0;
+ }
+ .average-skill {
+ color: var(--theme-darker-text);
+ font-size: 0.9rem;
+ }
+
+ .has-blurred-background #categories {
+ width: 47rem;
+ }
+
+ .technoblade-never-dies {
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ background: rgba(0, 0, 0, 0.1);
+ padding: 0.75em;
+ border-radius: 1em;
+
+ width: fit-content;
+ position: relative;
+ top: -1em;
+ }
+</style>